package com.epic.followup.service.app.impl;

import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.epic.followup.conf.PatientConfig;
import com.epic.followup.conf.FollowupStaticConfig;
import com.epic.followup.conf.WeChatConfig;
import com.epic.followup.model.app.AppPatientModel;
import com.epic.followup.repository.app.AppPatientRepository;
import com.epic.followup.service.app.AppPatientService;
import com.epic.followup.temporary.DealMessageResponse;
import com.epic.followup.temporary.app.patient.*;
import com.epic.followup.util.DateTimeUtils;
import net.jodah.expiringmap.ExpirationPolicy;
import net.jodah.expiringmap.ExpiringMap;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

@Service
public class AppPatientServiceImpl implements AppPatientService {

    private ExpiringMap<String, String> loginCodeMap;//登录验证码
    private ExpiringMap<String, String> resetCodeMap; // 重置密码验证码
    private ExpiringMap<String, String> registerCodeMap; // 注册验证码
    private org.slf4j.Logger log = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private AppPatientRepository appPatientRepository;
    @Autowired
    private WeChatConfig weChatConfig;

    public AppPatientServiceImpl(){
        this.loginCodeMap = ExpiringMap.builder()
                .maxSize(FollowupStaticConfig.MAX_USERNUM)
                .expiration(1, TimeUnit.MINUTES) // 1分钟有效
                .expirationPolicy(ExpirationPolicy.CREATED)
                .variableExpiration()
                .build();
        this.resetCodeMap = ExpiringMap.builder()
                .maxSize(FollowupStaticConfig.MAX_USERNUM)
                .expiration(1, TimeUnit.MINUTES) // 1分钟有效
                .expirationPolicy(ExpirationPolicy.CREATED)
                .variableExpiration()
                .build();
        this.registerCodeMap = ExpiringMap.builder()
                .maxSize(FollowupStaticConfig.MAX_USERNUM)
                .expiration(1, TimeUnit.MINUTES) // 1分钟有效
                .expirationPolicy(ExpirationPolicy.CREATED)
                .variableExpiration()
                .build();
    }

    @Override
    public DealMessageResponse sendRegisterCode(String tel) {
        DealMessageResponse res = new DealMessageResponse();
        if (this.registerCodeMap.get(tel) != null){
            res.setErrorMsg("1分钟内已发送过验证码，请查收.");
            res.setErrorCode(502);
            return res;
        }

        // 测试代码
        String code = DateTimeUtils.generateCode();
        this.registerCodeMap.put(tel, code);
        if (!this.sendCode(tel, "SMS_183763062", code)){
            res.setErrorMsg("短信发送失败，请联系网站管理员.");
            res.setErrorCode(502);
            return res;
        }

        res.setErrorCode(200);
        res.setErrorMsg("发送成功");
        return res;
    }

    @Override
    public DealMessageResponse sendLoginCode(String tel) {
        DealMessageResponse res = new DealMessageResponse();
        if (this.loginCodeMap.get(tel) != null){
            res.setErrorMsg("1分钟内已发送过验证码，请查收.");
            res.setErrorCode(502);
            return res;
        }

        // 测试代码
        String code = DateTimeUtils.generateCode();
        this.loginCodeMap.put(tel, code);
        if (!this.sendCode(tel, "SMS_204106817", code)){
            res.setErrorMsg("短信发送失败，请联系网站管理员.");
            res.setErrorCode(502);
            return res;
        }

        res.setErrorCode(200);
        res.setErrorMsg("发送成功");
        return res;
    }

    @Override
    public DealMessageResponse sendResetPasswordCode(String tel) {
        DealMessageResponse res = new DealMessageResponse();
        if (this.resetCodeMap.get(tel) != null){
            res.setErrorMsg("1分钟内已发送过验证码，请查收.");
            res.setErrorCode(502);
            return res;
        }

        // 测试代码
        String code = DateTimeUtils.generateCode();
        this.resetCodeMap.put(tel, code);
        if (!this.sendCode(tel, "SMS_183770245", code)){
            res.setErrorMsg("短信发送失败，请联系网站管理员.");
            res.setErrorCode(502);
            return res;
        }

        res.setErrorCode(200);
        res.setErrorMsg("发送成功");
        return res;
    }

    @Override
    public AppLoginbyCodeResponse loginbyCode(AppLoginbyCodeRequest req){
        AppLoginbyCodeResponse res=new AppLoginbyCodeResponse();
        Optional<AppPatientModel> ou = appPatientRepository.findByTel(req.getTel());
        if (!ou.isPresent()){
            res.setErrorMsg("用户不存在.");
            res.setErrorCode(504);
            return res;
        }
        AppPatientModel u = ou.get();
        if (loginCodeMap.get(u.getTel())!= null && loginCodeMap.get(u.getTel()).equals(req.getCode())){
            res.setErrorMsg("登录成功");
            res.setErrorCode(200);
            res.setPassword(u.getPassword());
            return res;
        }else {
            res.setErrorMsg("验证码错误或已失效.");
            res.setErrorCode(505);
            return res;
        }
    }

    @Override
    public DealMessageResponse loginbyPassword(AppLoginbyPasswordRequest req){
        DealMessageResponse res = new DealMessageResponse();
        Optional<AppPatientModel> ob = appPatientRepository.findByTel(req.getTel());
        if (ob.isPresent()){
            if (!req.getPassword().equals(ob.get().getPassword())){
                res.setErrorCode(401);
                res.setErrorMsg("密码错误或账户不存在.");
                return res;
            }
        }else {
            res.setErrorCode(401);
            res.setErrorMsg("密码错误或账户不存在.");
            return res;
        }
        // 成功返回
        res.setErrorMsg("登录成功.");
        res.setErrorCode(200);
        return res;
    }

    @Override
    public DealMessageResponse register(AppRegisterRequest req){
        DealMessageResponse res= new DealMessageResponse();
        // 验证码校验
        if (this.registerCodeMap.get(req.getTel()) != null){
            if (!req.getCode().equals(this.registerCodeMap.get(req.getTel()))){
                res.setErrorCode(501);
                res.setErrorMsg("验证码不正确.");
                return res;
            }
        }else {
            res.setErrorCode(503);
            res.setErrorMsg("验证码不存在或已过期.");
            return res;
        }

        // 密码校验
        if (req.getPassword().equals("")){
            res.setErrorCode(506);
            res.setErrorMsg("密码不能为空.");
            return res;
        }

        // 手机号是否已存在
        if (this.appPatientRepository.findByTel(req.getTel()).isPresent()){
            res.setErrorCode(505);
            res.setErrorMsg("该手机号已注册.");
            return res;
        }
        AppPatientModel user= new AppPatientModel();
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        user.setCreateTime(df.format(new Date()));
        user.setTel(req.getTel());
        user.setPassword(req.getPassword());
        appPatientRepository.save(user);
        res.setErrorMsg("注册成功.");
        res.setErrorCode(200);
        return res;
    }

    @Override
    public DealMessageResponse resetPassword(AppRegisterRequest req){
        DealMessageResponse res = new DealMessageResponse();
        Optional<AppPatientModel> ou = appPatientRepository.findByTel(req.getTel());
        if (!ou.isPresent()){
            res.setErrorMsg("用户不存在.");
            res.setErrorCode(505);
            return res;
        }
        AppPatientModel u = ou.get();
        if (resetCodeMap.get(u.getTel())!= null && resetCodeMap.get(u.getTel()).equals(req.getCode())){
            res.setErrorMsg("修改成功");
            res.setErrorCode(200);
            u.setPassword(req.getPassword());
            appPatientRepository.save(u);
            return res;
        }else {
            res.setErrorMsg("验证码错误或已失效.");
            res.setErrorCode(506);
            return res;
        }
    }

    @Override
    public DealMessageResponse setInformation(AppInformationRequest req){
        DealMessageResponse res = new DealMessageResponse();
        Optional<AppPatientModel> ou = appPatientRepository.findByTel(req.getTel());
        if (!ou.isPresent()){
            res.setErrorMsg("用户不存在.");
            res.setErrorCode(505);
            return res;
        }
        AppPatientModel u = ou.get();
        u.setUserName(req.getUserName());
        u.setImg(req.getImg());
        u.setGender(PatientConfig.genders[req.getGender()]);
        u.setBirth(req.getBirth());
        u.setOccupation(req.getOccupation());
        u.setOccupationType(req.getOccupationType());
        u.setIsStudent(req.getIsStudent()==0?"否":"是");
        if(req.getIsStudent()!=0){
            u.setUniversity(req.getUniversity());
            u.setCollege(req.getCollege());
            u.setMajor(req.getMajor());
        }
        else{
            u.setUniversity("");
            u.setCollege("");
            u.setMajor("");
        }
        u.setUserType(PatientConfig.userType[req.getUserType()]);
        if(req.getUserType()==0){
            u.setDiseaseType("");
            u.setPsychoStatus("");
            u.setHospital("");
            u.setDepartment("");
            u.setTherapist("");
        }
        else{
            u.setDiseaseType(PatientConfig.diseaseType[req.getDiseaseType()]);
            u.setPsychoStatus(PatientConfig.psychoStauts[req.getPsychoStatus()]);
            if(req.getPsychoStatus()==0||req.getPsychoStatus()==1){
                u.setHospital(PatientConfig.hospitals[req.getHospital()]);
                if(req.getHospital()==0) {
                    u.setDepartment(req.getDepartment());
                    u.setTherapist(req.getTherapist());
                } else{
                    u.setDepartment("");
                    u.setTherapist("");
                }
            } else{
                u.setHospital("");
                u.setDepartment("");
                u.setTherapist("");
            }
        }
        appPatientRepository.save(u);
        res.setErrorMsg("修改成功");
        res.setErrorCode(200);
        return res;

    }


    /*
     * 注册tempid : SMS_183763062
     * 修改密码： SMS_183770245
     * 验证码登录：SMS_204106817
     */
    public Boolean sendCode(String tel, String templateCode, String code) {
        DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", weChatConfig.getAli_access_key_id(), weChatConfig.getAli_access_key_secret());
        IAcsClient client = new DefaultAcsClient(profile);

        CommonRequest request = new CommonRequest();
        request.setSysMethod(MethodType.POST);
        request.setSysDomain("dysmsapi.aliyuncs.com");
        request.setSysVersion("2017-05-25");
        request.setSysAction("SendSms");
        request.putQueryParameter("RegionId", "cn-hangzhou");
        request.putQueryParameter("PhoneNumbers", tel);
        request.putQueryParameter("SignName", "迈思智能");
        request.putQueryParameter("TemplateCode", templateCode);
        request.putQueryParameter("TemplateParam", "{\"code\":\"" + code + "\"}");
        try {
            CommonResponse response = client.getCommonResponse(request);
            log.info(response.getData());
        } catch (ServerException e) {
            e.printStackTrace();
            return false;
        } catch (ClientException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
}
